﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;

using SharedGenomics.Core;
using SharedGenomics.Workbench.Core;
using SharedGenomics.Domain;

namespace SharedGenomics.Workbench.Services
{
    public class DataFilterService : IDataFilterService
    {
        public DataFilterService(ILoginManager loginManager)
        {
            this.LoginManager = loginManager;
        }

        public FilterResult ApplyFilters(int fileSetId, FilterParameterSetInfo filterParameters, IEnumerable<string> watchList)
        {
            filterParameters.ThrowIfNull("filterParameters");
            ExceptionHelper.ThrowIf<InvalidOperationException>(!this.LoginManager.IsLoggedIn, "Cannot apply filters - user is not logged in");

            using (var filterClient = new FilterService.FilterServiceClient())
            {
                //apply login credentials to proxy
                //TODO: use login guard...?
                this.LoginManager.LoginCredentials.ApplyToWCFProxy<FilterService.IFilterService>(filterClient);

                //apply submit filter request
                var cateogricallyFilteredIndividuals = filterClient.ApplyFilters(fileSetId, filterParameters);

                //wait until the filter job has finished
                JobStatus filterJobStatus;
                do
                {
                    System.Threading.Thread.Sleep(1000);
                    filterJobStatus = filterClient.GetFilterJobStatus();

                    ExceptionHelper.ThrowIf<Exception>(filterJobStatus.In(JobStatus.Failed, JobStatus.Cancelled), "Filter job failed");
                } while (filterJobStatus != JobStatus.Finished);

                //collate results with the categorical filter results returned in the initial call
                string[] watchListArray = (watchList ?? Enumerable.Empty<string>()).ToArray();
                FilterResult filterResults = filterClient.GetFilterResults(watchListArray);
                filterResults.FilteredEntities.AddRange(cateogricallyFilteredIndividuals.CategoricallyFilteredIndividuals);

                return filterResults;
            }
        }

        private ILoginManager LoginManager { get; set; }
    }
}
